//package com.my.thread.retry.test;
//
//import cn.hutool.http.HttpRequest;
//import cn.hutool.http.HttpResponse;
//import com.alibaba.fastjson.JSONObject;
//import com.github.rholder.retry.RetryException;
//import com.github.rholder.retry.Retryer;
//import com.my.geojson.test.wfs.exception.GeoXmlQlException;
//import com.my.geojson.test.wfs.utils.BtoaEncode;
//import com.my.geojson.test.wfs.utils.XMLUtils;
//import com.my.geojson.test.wfs.xmlGenerate.WFSTXmlGenerate;
//import com.my.geojson.test.wfs.xmlGenerate.impl.InsertUpdateWfsXmlGenerate;
//import lombok.extern.slf4j.Slf4j;
//import org.apache.commons.lang3.StringUtils;
//import org.dom4j.Document;
//import org.geotools.data.postgis.PostgisNGDataStoreFactory;
//import org.geotools.data.shapefile.ShapefileDataStore;
//import org.geotools.feature.AttributeTypeBuilder;
//import org.geotools.feature.FeatureCollection;
//import org.geotools.feature.FeatureIterator;
//import org.geotools.feature.simple.SimpleFeatureTypeBuilder;
//import org.geotools.referencing.CRS;
//import org.opengis.feature.Feature;
//import org.opengis.feature.Property;
//import org.opengis.feature.simple.SimpleFeature;
//import org.opengis.feature.simple.SimpleFeatureType;
//import org.opengis.feature.type.AttributeDescriptor;
//import org.opengis.feature.type.GeometryDescriptor;
//import org.opengis.referencing.FactoryException;
//import org.opengis.referencing.crs.CoordinateReferenceSystem;
//import org.springframework.beans.factory.annotation.Autowired;
//import org.springframework.beans.factory.annotation.Value;
//import org.springframework.http.HttpHeaders;
//import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
//import org.springframework.stereotype.Service;
//
//import java.io.*;
//import java.nio.charset.Charset;
//import java.util.*;
//import java.util.concurrent.ExecutionException;
//
//
//@Slf4j
//@Service
//public class GeoToolsManager {
//
//    public static final int CREATE = 0;
//    public static final int APPEND = 1;
//    public static final int OVERWRITE = 2;
//
//    private static CoordinateReferenceSystem crs4490;
//
//    @Autowired
//    private Retryer<Boolean> retryer;
//    @Autowired
//    private ThreadPoolTaskExecutor taskExecutor;
//
//    public GeoToolsManager() {
//        try {
//            crs4490 = CRS.decode("EPSG:4490");
//        } catch (FactoryException e) {
//            e.printStackTrace();
//        }
//    }
//
//    /**
//     * 根据数据库连接参数，获取数据源
//     *
//     * @return
//     * @throws IOException
//     */
//    private DataStore getPostgisDataStore(String host, String port, String user, String password, String database, String schema) throws IOException {
//        Map<String, Object> params = new HashMap<>();
//        params.put("dbtype", "postgis");
//        params.put("host", host);
//        params.put("port", port);
//        params.put("schema", schema);
//        params.put("database", database);
//        params.put("user", user);
//        params.put("passwd", password);
//        params.put(PostgisNGDataStoreFactory.LOOSEBBOX.key, true);
//        /**
//         * 开启下面后测试数据（7000+要素）由原来的19秒加快到13秒
//         */
//        params.put(PostgisNGDataStoreFactory.PREPARED_STATEMENTS.key, true);
//        System.out.println("连接数据库");
//        return DataStoreFinder.getDataStore(params);
//    }
//
//    public boolean shp2postgis(String shppath, String host, String port, String user, String password, String database, String schema, String tablename, String encode, int option) {
//        // 首先尝试连接数据库
//        DataStore pgDatastore = null;
//        try {
//            pgDatastore = getPostgisDataStore(host, port, user, password, database, schema);
//        } catch (IOException e) {
//            e.printStackTrace();
//            System.err.println("连接数据库失败");
//            return false;
//        }
//
//        // 尝试读取shp
//        ShapefileDataStore shpDataStore = null;
//        try {
//            shpDataStore = createShpDataStore(shppath, encode);
//        } catch (IOException e) {
//            e.printStackTrace();
//            System.err.println("读取shp失败");
//            return false;
//        } catch (FactoryException e) {
//            e.printStackTrace();
//            System.err.println("读取shp失败");
//            return false;
//        }
//
//        // 写入数据
//        return writePostGIS(pgDatastore, shpDataStore, tablename, option);
//    }
//
//    /**
//     * 根据shp文件创建数据源
//     *
//     * @param shppath
//     * @param encode
//     * @return
//     * @throws IOException
//     * @throws FactoryException
//     */
//    private ShapefileDataStore createShpDataStore(String shppath, String encode) throws IOException, FactoryException {
//        ShapefileDataStore shapefileDataStore = new ShapefileDataStore(new File(shppath).toURI().toURL());
//        // 根据用户指定的字符集编码设置解析编码
//        shapefileDataStore.setCharset(Charset.forName(encode));
//        // 如果没有指定坐标系，则强制使用4490
//        CoordinateReferenceSystem crs = shapefileDataStore.getSchema().getCoordinateReferenceSystem();
//        if (null == crs) {
//            crs = crs4490;
//            shapefileDataStore.forceSchemaCRS(crs);
//        }
//        // 根据数据源获取数据类型
//        return shapefileDataStore;
//    }
//
//    /**
//     * 根据数据源获取要素集合的迭代器
//     *
//     * @param dataStore
//     * @return
//     * @throws IOException
//     */
//    private FeatureIterator getIterator(ShapefileDataStore dataStore) throws IOException {
//        // 获取shp数据源
//        FeatureSource featureSource = dataStore.getFeatureSource();
//        FeatureCollection featureCollection = featureSource.getFeatures();
//        return featureCollection.features();
//    }
//
//    /**
//     * 根据一个shp要素类型创建一个新的要素类型
//     *
//     * @param tablename
//     * @param shpfeaturetype
//     * @return
//     */
//    private SimpleFeatureType createPostGISType(String tablename, SimpleFeatureType shpfeaturetype) {
//        SimpleFeatureTypeBuilder typeBuilder = new SimpleFeatureTypeBuilder();
//        // 这些需要设置下默认空间字段，否则不会识别
//        typeBuilder.setDefaultGeometry("geom");
//        // 这里设置一下名称，当shp文件名是大写时需要换成小写
//        typeBuilder.setName(tablename);
//        // 设置坐标系，单独设置没有起到作用
//        CoordinateReferenceSystem crs = shpfeaturetype.getCoordinateReferenceSystem();
//        typeBuilder.setCRS(crs);
//        // 新创建一个属性描述集合
//        List<AttributeDescriptor> attributeDescriptors = new ArrayList<>();
//        for (AttributeDescriptor attributeDescriptor : shpfeaturetype.getAttributeDescriptors()) {
//            //属性构造器
//            AttributeTypeBuilder build = new AttributeTypeBuilder();
//            build.init(attributeDescriptor.getType());
//            build.setNillable(true);
//            //获取字段名,改为小写
//            String name = StringUtils.isNotEmpty(attributeDescriptor.getLocalName()) ? attributeDescriptor.getLocalName().toLowerCase() : attributeDescriptor.getLocalName();
//            if (attributeDescriptor instanceof GeometryDescriptor) {
//                //修改空间字段名
//                name = "geom";
//            }
//            //设置字段名
//            build.setName(name);
//            //创建新的属性类
//            AttributeDescriptor descriptor = build.buildDescriptor(name, attributeDescriptor.getType());
//            attributeDescriptors.add(descriptor);
//        }
//        typeBuilder.addAll(attributeDescriptors);
//        return typeBuilder.buildFeatureType();
//    }
//
//    /**
//     * 将shp数据源写入postgis数据源
//     *
//     * @param pgDatastore
//     * @param shpDataStore
//     * @param tablename
//     * @param option
//     * @return
//     * @throws IOException
//     */
//    private boolean writePostGIS(DataStore pgDatastore, ShapefileDataStore shpDataStore, String tablename, int option) {
//        SimpleFeatureType shpfeaturetype = null;
//        try {
//            shpfeaturetype = shpDataStore.getSchema();
//        } catch (IOException e) {
//            e.printStackTrace();
//            System.err.println("shp读取失败");
//            return false;
//        }
//        // 原shp数据源的迭代器
//        FeatureIterator iterator = null;
//        try {
//            iterator = getIterator(shpDataStore);
//        } catch (IOException e) {
//            e.printStackTrace();
//            System.err.println("shp读取失败");
//            return false;
//        }
//
//        // 新建一个postgis要素类型构造器
//        SimpleFeatureType postGISType = this.createPostGISType(tablename, shpfeaturetype);
//        // 新建一个事务
//        Transaction transaction = new DefaultTransaction();
//        // 新建一个要素写对象
//        FeatureWriter<SimpleFeatureType, SimpleFeature> featureWriter = null;
//        try {
//            // 表操作
//            switch (option) {
//                case CREATE:
//                    pgDatastore.createSchema(postGISType);
//                    System.out.println("postgis创建数据表成功");
//                    break;
//                case APPEND:
//                    break;
//                case OVERWRITE:
//                    pgDatastore.removeSchema(tablename);
//                    System.out.println("postgis删除数据表成功");
//                    pgDatastore.createSchema(postGISType);
//                    System.out.println("postgis创建数据表成功");
//                    break;
//                default:
//                    System.err.println("非法操作");
//                    return false;
//            }
//            // 要素操作
//            featureWriter = pgDatastore.getFeatureWriterAppend(tablename, transaction);
//            System.out.println("开始写入");
//            Date startTime = new Date();
//            // 定义循环用到的变量
//            Feature feature = null;
//            SimpleFeature simpleFeature = null;
//            Collection<Property> properties = null;
//            Property property = null;
//            String pname = null;
//            Object pvalue = null;
//            while (iterator.hasNext()) {
//                feature = iterator.next();
//                simpleFeature = featureWriter.next();
//                properties = feature.getProperties();
//                Iterator<Property> propertyIterator = properties.iterator();
//                while (propertyIterator.hasNext()) {
//                    property = propertyIterator.next();
//                    pname = property.getName().toString().toLowerCase();
//                    if ("the_geom".equals(pname)) {
//                        pname = "geom";
//                    }
//                    // 如果值是空字符串则换成Null,表示无值
//                    pvalue = property.getValue();
//                    if (null == pvalue || (null != pvalue && StringUtils.isEmpty(property.getValue().toString()))) {
//                        pvalue = null;
//                    }
//                    simpleFeature.setAttribute(pname, pvalue);
//                }
//                featureWriter.write();
//            }
//            // 最后提交事务，可以加快导入速度
//            transaction.commit();
//            Date endTime = new Date();
//            System.out.println("写入结束,共耗时：" + (endTime.getTime() - startTime.getTime()));
//            System.out.println("shp导入postgis成功");
//            return true;
//        } catch (IOException e) {
//            try {
//                transaction.rollback();
//            } catch (IOException ioException) {
//                ioException.printStackTrace();
//            }
//            return false;
//        } finally {
//            try {
//                transaction.close();
//            } catch (IOException e) {
//                e.printStackTrace();
//            }
//            if (null != iterator) {
//                iterator.close();
//            }
//            if (null != featureWriter) {
//                try {
//                    featureWriter.close();
//                } catch (IOException e) {
//                    e.printStackTrace();
//                }
//            }
//            shpDataStore.dispose();
//            pgDatastore.dispose();
//        }
//    }
//
//
//    private HttpHeaders createAuthorHeader(String username, String password) {
////        HttpHeaders headers = RestUtil.getHeaderApplicationJson();
//        HttpHeaders headers = new HttpHeaders();
//        headers.add("Authorization",
//                "Basic " +
//                        BtoaEncode.botaEncodePassword(username + ":" + password));
//        return headers;
//    }
//
//    @Value("${geoserver.wfs.error.path:D:\\tmp\\error.xml}")
//    private String path;
//
//    private String xmlString = null;
//    /**
//     *
//     * @param path 输出的地址
//     * @param content 写入的内容
//     */
//    private void writeFile2Disk(String path,String content){
//        File file = new File(path);
//        if (!file.getParentFile().exists()) {
//            boolean result = file.getParentFile().mkdirs();
//        }
//        FileOutputStream fos= null;
//        OutputStreamWriter osw= null;
//        BufferedWriter  bw= null;
//        try {
//            fos = new FileOutputStream(file);
//            osw = new OutputStreamWriter(fos, "UTF-8");
//            bw = new BufferedWriter(osw);
//            bw.write(content);
//        } catch (Exception e) {
//            e.printStackTrace();
//            log.error("=====> 写入error xml 失败",e);
//        } finally {
//            //注意关闭的先后顺序，先打开的后关闭，后打开的先关闭
//            try {
//                if(bw!=null){
//                    bw.close();
//                }
//                if(osw!=null){
//                    osw.close();
//                }
//                if(fos!=null){
//                    fos.close();
//                }
//            } catch (IOException e) {
//                e.printStackTrace();
//                log.error("file流关闭失败,",e);
//            }
//        }
//
//
//    }
//
//    /**
//     *
//     * @param ip
//     * @param port
//     * @param username
//     * @param password
//     * @param typeName
//     * @param variables 要插入的参数
//     * @param params 要进行修改的数据唯一编号
//     * @return
//     * @throws Exception
//     */
//    public void insertUpdateByGeoWfs(String businessId,String updateUser,String ip, String port, String username, String password, String typeName, JSONObject variables, Map<String, Object> params){
//        taskExecutor.execute(()->{
//            try {
//                retryer.call(()->{
//                    try {
//                        this.send2GeoWfs(businessId,updateUser,ip, port, username, password, typeName, variables, params,
//                                InsertUpdateWfsXmlGenerate.class);
//                        //成功则释放xmlString
//                        this.xmlString = null;
//                        return true;
//                    }catch (GeoXmlQlException e){
//                        log.error("请求失败,{}",e);
//                        return false;
//                    }
//                });
//            } catch (ExecutionException e) {
//                e.printStackTrace();
//                this.writeFile2Disk(this.path,this.xmlString);
//                log.error("线程错误",e);
//            } catch (RetryException e) {
//                e.printStackTrace();
//                log.error("重试错误",e);
//                this.writeFile2Disk(this.path,this.xmlString);
//            }
//        });
//    }
//
//    private JSONObject send2GeoWfs(String businessId,String updateUser,String ip, String port, String username, String password, String typeName, JSONObject variables, Map<String, Object> params, Class<? extends WFSTXmlGenerate> c) throws Exception {
//        HttpHeaders headers = this.createAuthorHeader(username, password);
//        WFSTXmlGenerate generate = c.newInstance();
//        Document document = generate.createXml(businessId,updateUser,typeName, "http://" + ip + ":" + port + "/geoserver/wfs", variables, params);
////        log.info(document.asXML());
//        this.xmlString = document.asXML();
//        String url = "http://" + ip + ":" + port + "/geoserver/wfs";
//
//        HttpResponse response = HttpRequest.post(url)
//                .header(headers)//头信息，多个头信息多次调用此方法即可
//                .body(document.asXML())//表单内容
//                .timeout(20000)//超时，毫秒
//                .execute();
////        ResponseEntity<String> response =
////                HttpUtil.get()
////                RestUtil.request(,
////                HttpMethod.POST, headers, null,, String.class);
////        if(response.getStatusCode().is4xxClientError()){
////            throw new GeoXmlQlException("host无法请求!");
////        }
////        if(response.getStatusCode().is5xxServerError()){
////            throw new GeoXmlQlException("系统错误!");
////        }
//        log.info(response.body());
//        int status = response.getStatus();
//        if(200==status && response.body().contains("SUCCESS")){
//            return XMLUtils.xmltoJson(response.body());
//        }
//        throw new GeoXmlQlException("请求错误!");
//    }
//
//}
//
//
